package com.ibeetl.eval.ast;

import java.util.Map;

import org.beetl.core.Context;
import org.beetl.core.misc.ALU;
import org.beetl.core.statement.ArthExpression;
import org.beetl.core.statement.Expression;

import com.ibeetl.eval.TreeNode;

public  class SafeArthExpression extends ArthExpression{
	public SafeArthExpression(ArthExpression ar) {
		super(ar.a, ar.b,ar.arthMode,ar.token);
		
	}
	
	public Object evaluate(Context ctx)
	{
		Object x = a.evaluate(ctx);
		Object y = b.evaluate(ctx);
		switch (arthMode)
		{
			case PLUS:
				return ALU.plus(x, y, a, b);
			case MIN:
				return ALU.minus(x, y, a, b);
			case MUL:
				return ALU.mult(x, y, a, b);
			case DIV:
				return div(x,y,a,b,ctx);
//				return ALU.div(x, y, a, b);
			case MOD:
				return ALU.mod(x, y, a, b);

			default:
				throw new RuntimeException("不可能发生");

		}

	}
	
	/*对除法运算进行增强*/
	protected Object div(Object x,Object y,Expression a,Expression b,Context ctx){
	
		//表达式节点传节点名字
		String nodeName = (String)ctx.getGlobal("_nodeName");
		Map exceptionConfig =null;
		TreeNode node  = (TreeNode) ctx.getGlobal("_root");
		TreeNode root = getRootNode(node);
		TreeNode varNode = root.findTreeNodeByName(nodeName+"异常");
		if(varNode!=null){
			 exceptionConfig = (Map)varNode.getResult();
		}else{
			//没有找到配置项目，正常计算
			return ALU.div(x, y, a, b);
		}
		
		
		//可能有特殊处理的
		Double z1 = ((Number)x).doubleValue();
		Double z2 = ((Number)y).doubleValue();
		
		if(z1==0){
			 Object value = getData(exceptionConfig,"分子为0",a);
			 if(value==null){
				 throw new RuntimeException("分子为0,但未配置分子异常数据项目");
			 }
			 return value;
		}else if(z2==0){
			Object value = getData(exceptionConfig,"分母为0",b);
			 if(value==null){
				 throw new RuntimeException("分母为0,但未配置分母异常数据项目");
			 }
			 return value;
		}else{
			//正常计算
			return ALU.div(x, y, a, b);
		}
		
		
	}
	/*TODO,与ExvrlVarRef重复了*/
	private TreeNode getRootNode(TreeNode node){
		TreeNode temp = null;
		while(node.getParentNode()!=null){
			temp = node.getParentNode();;
			node = temp;
		}
		return temp;
	}
	
	private Object getData(Map config,String key,Expression expression){
		Object ret = config.get(key);
		if(ret==null){
			if(expression instanceof ExpressionWrapper){
				ExpressionWrapper wrapper = (ExpressionWrapper)expression;
				key = wrapper.expStr;
			}
			ret = config.get("当"+key+"为0");
		}
		
		return ret;
	}
	
	
}